import repeater
import serial

class TXU1256(repeater.AbstractRepeater):
    class Commands:
        MODE_ON = "FF011"
        MODE_OFF = "FF012" #not working
        MODE_RELAIS = "FF013"
        MODE_STANDBY = "FF010" #not working?

        ADC_STATUS = "MV"
   
        STOP_TX = "FO010"
        START_TX = "FO011"
    
    STX = "\x02"
    BLOCK1 = "00000000"
    ID = "FFFF"
    FILLER = "00"
    END = "\x03"
    
    def __init__(self):
        self.serialPort = serial.Serial(
    port=0, #number of device, numbering starts at
                            #zero. if everything fails, the user
                            #can specify a device string, note
                            #that this isn't portable anymore
                            #if no port is specified an unconfigured
                            #an closed serial port object is created
    baudrate=9600, #baudrate
    bytesize=serial.SEVENBITS, #number of databits
    parity=serial.PARITY_EVEN, #enable parity checking
    stopbits=serial.STOPBITS_ONE, #number of stopbits
    timeout=3, #set a timeout value, None for waiting forever
    xonxoff=0, #enable software flow control
    rtscts=0               #enable RTS/CTS flow control
    
    
    )
        self.serialPort.open()
        assert(self.serialPort.isOpen())
        
    
    def toProtocolHex(self, upper):
        
        assert(upper >= 0 and upper < 16)
        if upper < 10:
            upper = str(upper)
        else:
            if upper == 10:
                upper = 'A'
            if upper == 11:
                upper = 'B'
            if upper == 12:
                upper = 'C'
            if upper == 13:
                upper = 'D'
            if upper == 14:
                upper = 'E'
            if upper == 15:
                upper = 'F'
        return upper

    def __calculateCRC(self, value):
        sum = 0
        for c in value:
            sum += ord(c)
            if sum > 255:
                sum -= 256
        return sum

    
    #build a message to the relais format
    def encodeString(self, data):
        x = self.STX
        x += self.BLOCK1
        x += self.ID
        x += self.FILLER
        length = len(data)

        #upper nibbel
        x += self.toProtocolHex(length / 16)
        x += self.toProtocolHex(length - (16 * (length / 16)))
        x += data
  
        sum = self.__calculateCRC(x)
  
 
        #upper nibbel
        upper = sum / 16
        x += self.toProtocolHex(upper)
        #lower nibbel
        lower = sum - ((sum / 16) * 16)
        x += self.toProtocolHex(lower)
        x += self.END
        return x
    
        #BYTE                    VALUE
#; **    00H                    START        02H=STX
#; **    01H-04H                ID           0055    0055H => SERIAL#=XXXX0085
#; **    05H-0CH                FILLER       00000000
#; **    0DH                    MSG#         0    0-9
#; **    0EH-10H                LENGTH       10    10H BYTES DATA
#; **    11H-(END-03H)          DATA
#; **    (END-03H)-(END-01H)    CRC          FE    CHECKSUM-8 00H-(END-03H) => FEH
#; **    END                    END          03H=ETX
    def getLength(self):
        value =  self.serialPort.read(17) #first 17 chars form the header read them!
        
        assert(len(value) == 17)
        #print value
        
        start = value[0]
        
        #print "START:", start
        assert(start == self.STX)
        
        id = value[1:5]
        #print "ID:", id
         
        filler = value[6:14]
        #print "FILLER:" + filler
        
        msg = value[14]
        #print "MSG:" , msg
        
        length = value[15:17]
        #print "LENGTH:", length
        
        
        
        return int(length, 16) + 3, value #3 bytes from the end
    
    def getData(self):
        length, prevalue = self.getLength()
        
        value = self.serialPort.read(length)
        
        assert(len(value) == length)
        
        end = value[-1]
        #print "END:", end
        
        assert(end == self.END)
        
        ##check the checksum
        calculatedChecksum = self.__calculateCRC(prevalue + value[:-3])
        
        sendCechksum = int(value[-3:-1], 16)
        
        assert(calculatedChecksum == sendCechksum)
        
        
        #return only data
        return value[:-3]
        
        
    def __doCommand(self, command, validate):
        commandstring = self.encodeString(command)
        self.serialPort.write(commandstring)
        
        data = self.getData()
        if validate :
            assert(data == command)
        return data
     
    def setModeOn(self):
        self.__doCommand(self.Commands.MODE_ON, True)
        
    def setModeOff(self):
       self.__doCommand(self.Commands.MODE_OFF, True)
        
    def setModeRelais(self):
        doCommand(self.Commands.MODE_RELAIS, True)
    
    def startTransmit(self):
        self.__doCommand(self.Commands.START_TX, True)
        
    def stopTransmit(self):    
        self.__doCommand(self.Commands.STOP_TX, True)
    
    def getSignalToNoiseRatio(self):
        return self.readADC()[8]
    
    
        
#        54        TEMPERATURE => 54H
#; **                000        REFLECT => 000H
#; **                000        FORWARD => 000H
#; **                03        CURRENT => 03H
#; **                069        TX POWER => 069H
#; **                0C        SQUELCH HIGH LEVEL => 0CH
#; **                08        SQUELCH LOW LEVEL => 08H
#; **                0F        CARRIER SENSE LEVEL => 0FH
#; **                01        S/N => 01 DB

        
    def readADC(self):
        value = self.__doCommand(self.Commands.ADC_STATUS, False)
        #check if command went okay
        assert(value[0:2] == self.Commands.ADC_STATUS)
        
        temperature = int(value[4:6], 16)
        #print "Temperatur:", temperature
        
        reflect = value[6:9]
        #print "Reflect:", reflect
        
        forward = value[9:12]
        #print "FORWARD:", forward
        
        current = value[12:14]
        #print "Current:", current
        
        txpower = value[14:17]
        #print "TXPOWER:", txpower
        
        sqlhigh = value[17:19]
        #print "SQL HIGH:" , sqlhigh
        
        sqllow = value[19:21]
        #print "SQL Low", sqllow
        
        carrier_sense_level = value[21:23]
        #print "CARRIER SENSE:", carrier_sense_level
        
        snr = int(value[23:25], 16)
        return temperature, reflect, forward, current, txpower, sqlhigh,sqllow, carrier_sense_level, snr
        #print "SNR:", snr
        